package com.wfh.mianshi.manager;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RScript;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.IntegerCodec;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Instant;
import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * @Author FengHuan Wang
 * @Date 2025/4/26 8:37
 * @Version 1.0
 */
@Service
@Slf4j
public class CounterManager {


    @Resource
    private RedissonClient redissonClient;

    /**
     * 增加并返回计数
     * @param key
     * @param timenterval
     * @param timeUnit
     * @param ttl
     * @return
     */
    public long incrAndGetCounter(String key, int timenterval, TimeUnit timeUnit, long ttl) throws IllegalAccessException {
        if (key == null){
            return 0;
        }
        // 根据时间粒度生成redis key
        long timeFactor;
        switch (timeUnit){
            case SECONDS:
                timeFactor = Instant.now().getEpochSecond() / timenterval;
                break;
            case MINUTES:
                timeFactor = Instant.now().getEpochSecond() /timenterval / 60;
                break;
            case HOURS:
                timeFactor = Instant.now().getEpochSecond() / timenterval / 3600;
                break;
            default:
                throw new IllegalAccessException("不合法的单位");
        }
        String redisKey = key + ":" + timeFactor;
        // lua脚本
        String luaScript =
                "if redis.call('exists', KEYS[1]) == 1 then " +
                        "  return redis.call('incr', KEYS[1]); " +
                        "else " +
                        "  redis.call('set', KEYS[1], 1); " +
                        "  redis.call('expire', KEYS[1], 180); " +  // 设置 180 秒过期时间
                        "  return 1; " +
                        "end";
        RScript script = redissonClient.getScript(IntegerCodec.INSTANCE);
        Object eval = script.eval(RScript.Mode.READ_WRITE,
                luaScript,
                RScript.ReturnType.INTEGER,
                Collections.singletonList(redisKey), ttl);
        return (long) eval;
    }
}
